package http;


import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.*;
import com.gargoylesoftware.htmlunit.javascript.host.Window;
import com.gargoylesoftware.htmlunit.util.UrlUtils;
import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.HttpUnitOptions;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebLink;
import http.util.ParseUtil;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.xml.sax.SAXException;
import user.User;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BasicRequest {
    private final String ip = "192.168.170.23";
    private final String url = "http://192.168.170.23";
    private final String defaultHeader = "application/x-www-form-urlencoded;charset=gb2312";
    private Request basicRequest;
    private OkHttpClient httpClient;
    public static Map<Long, List<Cookie>> idAndCookies = new HashMap<Long, List<Cookie>>();

    public BasicRequest() {
//        if (this.httpClient == null) {
        this.httpClient = new BasicHttpClient().getClient();
//        }
//        if (getBasicRequest() == null) {
//            return new http.BasicRequest().getBasicRequestBuilder();
//        }
        this.basicRequest = new Request.Builder()
                .addHeader("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
                .addHeader("connection", "keep-alive") //keep-alive
//                .addHeader("cookie", getCookie(url)) //"route=a79c11333bcfcab69beab260e38ff9cb; ASP.NET_SessionId=af4gtiqgxirq3p21hrrcsu55"
                .addHeader("host", getIp())
                .addHeader("origin", getUrl())
                .header("Accept-Encoding", "identity")
                .url(url)
                .build();
    }

    public Request getBasicRequest() {
        return basicRequest;
    }

    public String getWithLoginCookie(String uri) {
        Request request = this.getBasicRequest().newBuilder()
                .url(url + uri)
                .get()
                .build();
        String res = null;
        try {
            Response response = httpClient.newCall(request).execute();

            res = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return res;
    }

    public Response getWithLoginCookie2(String uri, String id) {
        System.out.println("getCookie:" + getCookie(Long.valueOf(id)));
        Request request = this.getBasicRequest().newBuilder()
                .header("cookie", getCookie(Long.valueOf(id))) //"route=a79c11333bcfcab69beab260e38ff9cb; ASP.NET_SessionId=af4gtiqgxirq3p21hrrcsu55"
                .url(url + uri)
                .get()
                .build();
        try {
            Response response = httpClient.newCall(request).execute();
            System.out.println("response:" + response.toString());
            return response;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getCommonViewStateByHtml(String responseHtml) throws IOException {
        String result = ParseUtil.parseScript(responseHtml);
        if (responseHtml != null) {
            Document doc = Jsoup.parse(responseHtml);
            Element viewStateElement = doc.select("input[name=__VIEWSTATE]").first();
            if (viewStateElement != null) {
                return (viewStateElement.val());
            }
        }
        return null;
    }

    public String getCommonViewState(String uri, String id, String xh) throws IOException {
        Request request = this.getBasicRequest().newBuilder()
                .header("cookie", getCookie(Long.valueOf(id))) //"route=a79c11333bcfcab69beab260e38ff9cb; ASP.NET_SessionId=af4gtiqgxirq3p21hrrcsu55"
                .addHeader("Referer", url + "/xs_main.aspx?xh=" + xh)
                .url(url + uri)
                .get()
                .build();
        Response response = httpClient.newCall(request).execute();

//        System.out.println("response:" + response.toString());
        String responseHtml = response.body().string();
        String result = ParseUtil.parseScript(responseHtml);

        Document doc = Jsoup.parse(responseHtml);
        Element viewStateElement = doc.select("input[name=__VIEWSTATE]").first();
        if (viewStateElement != null) {
            return (viewStateElement.val());
        }
        //System.out.println(result);
        return null;
    }

    public Response getWithLoginCookie2(String uri, String id, String xh) throws IOException {
//__EVENTTARGET=dpkcmcGrid%3AtxtPageSize&__EVENTARGUMENT=&__VIEWSTATE=&ddl_kcxz=&ddl_ywyl=%D3%D0&ddl_kcgs=&ddl_xqbs=1&ddl_sksj=&TextBox1=&Button2=%C8%B7%B6%A8&dpkcmcGrid%3AtxtChoosePage=1&dpkcmcGrid%3AtxtPag
        //System.out.println("getCookie:" + getCookie(Long.valueOf(id)));
        Request request = this.getBasicRequest().newBuilder()
                .header("cookie", getCookie(Long.valueOf(id))) //"route=a79c11333bcfcab69beab260e38ff9cb; ASP.NET_SessionId=af4gtiqgxirq3p21hrrcsu55"
                .addHeader("Referer", url + "/xs_main.aspx?xh=" + xh)
                .url(url + uri)
                .get()
                .build();

        //WebConversation wc = new WebConversation();
        //wc.putCookie("cookie", getCookie(Long.valueOf(id)));
        //WebResponse resp = wc.getResponse(url + uri);
//            WebLink link = resp.getLinkWith("下一页");
//            final WebClient webClient = new WebClient();
//            URL url = new URL("http://www.zhiwo.com/");
//            List<HtmlElement> active= (List<HtmlElement>);
//            HtmlPage page = webClient.getPage(url);
//            page.getDocumentElement().getElementsByAttribute("li", "class", "parent_filter_item");
//
//            for (HtmlElement htmlElement : active) {
//                HtmlPage page1 = htmlElement.click();
//
//System.out.println(page1.asXml());
//
//            }
//            link.click();
//        WebClient webclient = new WebClient();

        // 这里是配置一下不加载css和javaScript，因为httpunit对javascript兼容性不太好
//        webclient.getOptions().setCssEnabled(false);
//        webclient.getOptions().setJavaScriptEnabled(false);

//        // 做的第一件事，去拿到这个网页，只需要调用getPage这个方法即可
//        String cookieAll = getCookie(Long.valueOf(id)).split(";")[1];
//        String cookieName = cookieAll.split("=")[0];
//        String cookieValue = cookieAll.split("=")[1];
//        URL link = new URL(url + uri);
//        //WebClient wc2 = new WebClient();
//        WebConversation wc2 = new WebConversation();
//        //WebRequest request2 = new WebRequest(link);
//        WebConversation wc = new WebConversation();
//        HttpUnitOptions.setExceptionsThrownOnScriptError(false);// js运行错误时，是否抛出异
//        WebRequest req = new WebRequest(link);
//        //request2.setAdditionalHeader("Referer", url + "/xs_main.aspx?xh=" + xh);//设置请求报文头里的refer字段
//        req.setAdditionalHeader("Referer", url + "/xs_main.aspx?xh=" + xh);
//        //WebResponse resp = wc2.getResponse(req);

        ////设置请求报文头里的User-Agent字段
//        request2.setAdditionalHeader("User-Agent", "Mozilla/5.0 (Windows NT 5.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");
        //wc.addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 5.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");
        //wc.addRequestHeader和request.setAdditionalHeader功能应该是一样的。选择一个即可。
        //其他报文头字段可以根据需要添加
//            webclient.getCookieManager().setCookiesEnabled(true);//开启cookie管理
//            webclient.getCookieManager().addCookie(c);
//            webclient.addRequestHeader("Referer", url + "/xs_main.aspx?xh=" + xh);

        //wc2.getCookieManager().setCookiesEnabled(true);//开启cookie管理
//        wc2.getOptions().setJavaScriptEnabled(true);//开启js解析。对于变态网页，这个是必须的
//        wc2.getOptions().setCssEnabled(true);//开启css解析。对于变态网页，这个是必须的。
//        wc2.getOptions().setThrowExceptionOnFailingStatusCode(false);
//        wc2.getOptions().setThrowExceptionOnScriptError(false);

        //com.gargoylesoftware.htmlunit.util.Cookie c = new com.gargoylesoftware.htmlunit.util.Cookie(url, cookieName, cookieValue);
//        wc2.getCookieManager().addCookie(c);


        //HtmlPage htmlpage = webclient.getPage(url + uri);
//        while (run) {
//
//            if (page == null) {
//                System.out.println("采集 " + url + " 失败!!!");
//            }
//
//            System.out.println(page);
//            System.out.println(page.asText());
//            if (!page.asText().startsWith("三")) {
//                run = false;
//            }
//
//        }
//        try {
//            Thread.sleep(5000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        String content = page.asText();//网页内容保存在content里
//        if (content == null) {
//            System.out.println("采集 " + url + " 失败!!!");
//        }
//        System.out.println(content);
//            System.out.println(htmlpage);
//            System.out.println(htmlpage.getTextContent());
//            System.out.println(htmlpage.getBody().getTextContent());
//        final DomElement button = page.getElementById("dpkcmcGrid_btnNextPage");

//        // 我把结果转成String
//        String result = nextPage.asXml();
//        System.out.println(result);  //得到的是点击后的网页

//            WebResponse nextLink = wc.getCurrentPage();
//
//            System.out.println("nextLink:" + nextLink.getText());
//            Response response = httpClient.newCall(request).execute();
//            System.out.println("response:" + response.toString());
//            return response;
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        return null;
    }

    //接受id 19080101011 19080101012
    public String post(String uri, String bodyContent, String id) {
        //System.out.println("post中id " +id);
        Request request = this.getBasicRequest().newBuilder()
                .url(url + uri) //xstyk.aspx?xh=1908010101&xm=%CB%D5%B3%AC%CF%CD&gnmkdm=N121205
                .post(RequestBody.create(MediaType.parse(defaultHeader), bodyContent))
                .build();
        return handlerResponseCookie(request, Long.valueOf(id));
    }

    public String postWithLoginCookie(String uri, String bodyContent) {

        Request request = this.getBasicRequest().newBuilder()
//                .header("cookie", getCookie(url+uri)) //"route=a79c11333bcfcab69beab260e38ff9cb; ASP.NET_SessionId=af4gtiqgxirq3p21hrrcsu55"
                .url(url + uri) //xstyk.aspx?xh=1908010101&xm=%CB%D5%B3%AC%CF%CD&gnmkdm=N121205
                .post(RequestBody.create(MediaType.parse(defaultHeader), bodyContent))
                .build();

        String res = null;
        try {
            //    System.out.println("postWithLoginCookieXX: ");
            //     System.out.println(request.url());

            Response response = httpClient.newCall(request).execute();
            res = response.body().string();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    //cookie与数字绑定 绑定的什么？
//    synchronized
    public String postCommonWithLoginCookieAndViewState(String uri, String bodyContent, String id, String xh, String viewState) {
        Request request = null;
        if (viewState == null) {
            return null;
        }
        try {
            request = this.getBasicRequest().newBuilder()
                    .addHeader("Referer", url + "/xs_main.aspx?xh=" + xh)
                    .header("cookie", getCookie(Long.parseLong(id)))
                    .url(url + uri)
                    .post(RequestBody.create(MediaType.parse(defaultHeader),
                            bodyContent + "&__VIEWSTATE=" +
                                    URLEncoder.encode(viewState, "gb2312")))
                    .build();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String res = null;
        try {

            Response response = httpClient.newCall(request).execute();
            res = response.body().string();
        } catch (Exception e) {
            //e.printStackTrace();
        }
        return res;
    }

    synchronized
    public String postWithLoginCookieAndViewState(String uri, String bodyContent, String id, String className) {
//        System.out.println("postWithLoginCookieAndViewState-id" + id);
//        System.out.println("postWithLoginCookieAndViewState: " + url + uri);
//        System.out.println("postWithLoginCookieAndViewState-getCookie(url+uri)" + getCookie(Long.valueOf(id)));
//        System.out.println("postWithLoginCookieAndViewState-idToviewState" + User.idToViewState);
//        System.out.println("IdHAS? ViewState?" + User.idToViewState.get(id+className));
        Request request = null;
        try {
//            System.out.println("发包内容" +bodyContent + "&__VIEWSTATE=" +
//                    URLEncoder.encode(User.idToViewState.get(id+className), "gb2312"));
            request = this.getBasicRequest().newBuilder()
                    .header("cookie", getCookie(Long.parseLong(id))) //"route=a79c11333bcfcab69beab260e38ff9cb; ASP.NET_SessionId=af4gtiqgxirq3p21hrrcsu55"
                    .url(url + uri) //xstyk.aspx?xh=1908010101&xm=%CB%D5%B3%AC%CF%CD&gnmkdm=N121205
                    .post(RequestBody.create(MediaType.parse(defaultHeader),
                            bodyContent + "&__VIEWSTATE=" +
                                    URLEncoder.encode(User.idToViewState.get(id + className), "gb2312")))//VIEWSTATE
                    .build();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        String res = null;
        try {
//            System.out.println("postWithLoginCookie3: 测试的request " + request.url());
            Response response = httpClient.newCall(request).execute();
            res = response.body().string();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    public Response postWithLoginCookie2(String uri, String bodyContent, String cookieId) {
//        System.out.println("postWithLoginCookie2: " + url + uri);
//        System.out.println("postWithLoginCookie2-CC:" + cookieId);
        Request request = this.getBasicRequest().newBuilder()
                .url((url + uri)) //xstyk.aspx?xh=1908010101&xm=%CB%D5%B3%AC%CF%CD&gnmkdm=N121205
                .header("cookie", getCookie(Long.valueOf(cookieId))) //"route=a79c11333bcfcab69beab260e38ff9cb; ASP.NET_SessionId=af4gtiqgxirq3p21hrrcsu55"
                .post(RequestBody.create(MediaType.parse(defaultHeader), bodyContent))
                .build();
        try {
//            System.out.println("cx:");
//            System.out.println(request.toString());
//            System.out.println(request.url());
            return httpClient.newCall(request).execute();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //todo get
    //todo aop 设计模式 @after
    //处理登录后的cookie
    //根据id分类 方便随机cookie
    synchronized
    public String handlerResponseCookie(Request request, long id) {
        //19080101011
//        System.out.println("handlerResponseCookie");
        Response response = null;
        try {
            response = httpClient.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Headers headers = response.headers();
        HttpUrl url = request.url();
//        System.out.println("url" + url);
        List<Cookie> cookies = Cookie.parseAll(url, headers);
//        System.out.println(cookies);
        //这里先拿登录cookie了
        //之后以登录id x cookie 存储形式 给以后调用 先丢进cookie里
        if (cookies != null) {
//            System.out.println("保存cookies" + cookies);
//            System.out.println("url" + url);
//            User.idToViewState.put(i,cookies);
            //根据id存储cookie
            //这里不需要存viewState
            //目前使用的函数是user.login
            //url需要符合规范
//            httpClient.cookieJar().saveFromResponse(url, cookies);
            //让我们手动接管吧
            saveCookie(id, cookies);
//            System.out.println("idAndCookies: " + idAndCookies);
        }
        String res = null;
        try {
            res = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return res;
    }

    public String getIp() {
        return this.ip;
    }

    public String getUrl() {
        return this.url;
    }


    public OkHttpClient getHttpClient() {
        return httpClient;
    }

    //
//    public String getCookie(String url) {
//        System.out.println("GETcookie测试1");
//        if (this.basicRequest != null) {
////            System.out.println("getCookie"+this.basicRequest.url());
//            System.out.println("GETcookie测试2");
//            StringBuilder cookieStr = new StringBuilder();
////            List<Cookie> cookies = this.httpClient.cookieJar().loadForRequest(this.basicRequest.url());
//            List<Cookie> cookies = this.httpClient.cookieJar().loadForRequest(HttpUrl.parse(url));
////            System.out.println(this.basicRequest.url());
//            System.out.println(cookies);
//            for (Cookie cookie : cookies) {
//                cookieStr.append(cookie.name()).append("=").append(cookie.value() + ";");
//            }
//            System.out.println("cookieStr.toString()" + cookieStr.toString());
//            return cookieStr.toString();
//        }
//        return "";
//    }
    public String getCookie(long id) {
        if (this.basicRequest != null) {
            StringBuilder cookieStr = new StringBuilder();
            List<Cookie> cookies = idAndCookies.get(id);
//            System.out.println("getCookieId " + id  +" || "+ cookies);
            for (Cookie cookie : cookies) {
                cookieStr.append(cookie.name()).append("=").append(cookie.value() + ";");
            }
//            System.out.println("cookieStr.toString()" + cookieStr.toString());
            return cookieStr.toString();
        }
        return "";
    }

    public void saveCookie(Long id, List<Cookie> cookies) {
        System.out.println("保存Cookie:" + cookies + " id:" + id);
        idAndCookies.put(id, cookies);
    }

}

